﻿using System;
using System.ComponentModel;
using System.Windows;
using Azukit.Messaging;
using Azukit.ViewModel;
using Azukit.WPF.Environment;
using Hibiku.Models;
using Hibiku.Services;
using Hibiku.Twitter;
using Ninject;

namespace Hibiku
{
    public class HibikuEnvironment : AzukitEnvironment
    {
        public HibikuEnvironment()
            : base(CreateViewModelRegistry())
        {
        }

        #region Design mode services

        class DesignModeTwitterApi : ITwitterApi
        {
            #region ITwitterApi Members

            public event Action<EStream, System.Collections.Generic.IEnumerable<Tweet>> TweetsReceived;

            public event EventHandler Unauthorized = delegate { };

            public event EventHandler Authorized = delegate { };

            public bool IsAuthorized
            {
                get { return true; }
            }

            public AuthorizationResponse Authorization
            {
                get { return new AuthorizationResponse("dummy", "dummy", new TokenPair("dummy", "dummy")); }
            }

            public AuthorizationRequest GetAuthorizationRequest()
            {
                return new AuthorizationRequest("dummy", new TokenPair("dummy", "dummy"));
            }

            public void Authorize(string pin, TokenPair requestTokenPair)
            {
                Authorized(this, EventArgs.Empty);
            }

            public void GetTweets(EStream stream, long? sinceId)
            {

                TweetsReceived(EStream.HomeTimeline, new Tweet[] { DesignerData.TweetViewModel.Tweet });
            }

            public void Update(string text, long? inReplyToStatusId, Location location)
            {
            }

            public void StartStream(int userId)
            {
            }

            #endregion
        }

        class DesignModeApplicationConfigurationService : IApplicationConfigurationService
        {
            public DesignModeApplicationConfigurationService()
            {
                var filters = new FilterRuleModel[] {
                    new FilterRuleModel("Interesting", EFilterMatchAction.Highlight),
                    new FilterRuleModel("Noise", EFilterMatchAction.Delete)
                };
                Configuration = new ApplicationConfigurationModel(new AuthorizationResponse("1", "user", new TokenPair("token", "secret")), filters);
            }

            #region IApplicationConfigurationService Members

            public ApplicationConfigurationModel Configuration
            {
                get; private set;
            }

            public void Save()
            {
                var handlers = ConfigurationSaved;

                if(handlers != null) handlers(this, System.EventArgs.Empty);
            }

            public event System.EventHandler ConfigurationSaved;

            #endregion
        }

        #endregion

        private static bool IsDesignMode
        {
            get
            {
                var obj = new DependencyObject();

                return DesignerProperties.GetIsInDesignMode(obj);
            }
        }

        private static IViewModelRegistry CreateViewModelRegistry()
        {
            var configurationService = new ApplicationConfigurationService();
            var featureTrackingService = new EqatecAnalyticsFeatureTrackingService();
            var twitterApi = new TwitterApi(configurationService.Configuration.Authorization);

            var kernel = new StandardKernel();
            kernel.Bind<IFeatureTrackingService>().ToConstant(featureTrackingService);
            kernel.Bind<IGeoLocatorService>().To<WindowsGeoLocationService>();
            kernel.Bind<ITransceiver>().To<Transceiver>();

            if (IsDesignMode)
            {
                kernel.Bind<ITwitterApi>().To<DesignModeTwitterApi>();
                kernel.Bind<IApplicationConfigurationService>().To<DesignModeApplicationConfigurationService>();
            }
            else
            {
                kernel.Bind<ITwitterApi>().ToConstant(twitterApi);
                kernel.Bind<IApplicationConfigurationService>().ToConstant(configurationService);
            }

            var registry = new NinjectBasedViewModelRegistry(kernel);

            return registry;
        }

        public class NinjectBasedViewModelRegistry : IViewModelRegistry
        {
            private readonly IKernel _kernel;

            public NinjectBasedViewModelRegistry(IKernel kernel)
            {
                _kernel = kernel;
            }

            private IViewModel CreateViewModel(string key)
            {
                try
                {
                    var typeName = string.Format("{0}.ViewModels.{1}ViewModel", GetType().Assembly.GetName().Name, key);
                    var type = Type.GetType(typeName);
                    var viewModel = _kernel.Get(type) as IViewModel;

                    return viewModel;
                }
                catch (Exception ex)
                {
                    throw new ArgumentException("Unknown view model " + key, ex);
                }
            }

            #region IViewModelRegistry Members

            public IViewModel this[string key]
            {
                get { return CreateViewModel(key); }
            }

            #endregion
        }
    }
}
